package com.horay.statemachiedemo.multi.controller;

import com.horay.statemachiedemo.multi.builder.OrderStateMachineBuilder;
import com.horay.statemachiedemo.multi.enums.OrderState;
import com.horay.statemachiedemo.multi.event.OrderEvent;
import com.horay.statemachiedemo.multi.model.Order;
import com.horay.statemachiedemo.multi.persist.MemoryStateMachineMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Class description
 *
 * @author heyingcheng
 * @date 2020/10/23
 */
@Slf4j
@RestController
public class OrderController {

    private final BeanFactory beanFactory;

    private final OrderStateMachineBuilder orderStateMachineBuilder;

    private final StateMachinePersister<OrderState, OrderEvent, String> orderMemoryStateMachinePersister;

    private final StateMachinePersister<OrderState, OrderEvent, Order> orderDbStateMachinePersister;

    public OrderController(BeanFactory beanFactory, OrderStateMachineBuilder orderStateMachineBuilder, StateMachinePersister<OrderState, OrderEvent, String> orderMemoryStateMachinePersister, StateMachinePersister<OrderState, OrderEvent, Order> orderDbStateMachinePersister) {
        this.beanFactory = beanFactory;
        this.orderStateMachineBuilder = orderStateMachineBuilder;
        this.orderMemoryStateMachinePersister = orderMemoryStateMachinePersister;
        this.orderDbStateMachinePersister = orderDbStateMachinePersister;
    }

    @PostMapping("/order/pay")
    public String pay(String orderId) throws Exception {

        StateMachine<OrderState, OrderEvent> stateMachine = orderStateMachineBuilder.build(beanFactory);
        // 创建流程
        stateMachine.start();
        // 触发PAY事件
        Order order = new Order(orderId, "PAY-547568678", "PAY-广东省深圳市", "PAY-13435465465");
        Message<OrderEvent> message = MessageBuilder.withPayload(OrderEvent.PAY).setHeader(Order.class.getName(), order).build();
        stateMachine.sendEvent(message);
        // 获取状态
        log.info("OrderId:[{}], State:[{}]", orderId, stateMachine.getState().getId());
        return "SUCCESSS";

    }

    @PostMapping("/order/receive")
    public String receive(String orderId) throws Exception {

        StateMachine<OrderState, OrderEvent> stateMachine = orderStateMachineBuilder.build(beanFactory);
        // 创建流程
        stateMachine.start();
        // 触发RECEIVE事件
        Order order = new Order(orderId, "RECEIVE-547568678", "RECEIVE-广东省深圳市", "RECEIVE-13435465465");
        Message<OrderEvent> message = MessageBuilder.withPayload(OrderEvent.RECEIVE).setHeader(Order.class.getName(), order).build();
        stateMachine.sendEvent(message);
        // 获取状态
        log.info("OrderId:[{}], State:[{}]", orderId, stateMachine.getState().getId());
        return "SUCCESSS";

    }

    @PostMapping("/order/send/event")
    public String sendEvent(String orderId, String event) throws Exception {

        StateMachine stateMachine = MemoryStateMachineMap.FORM_STATE_MACHINE_MAP.get(orderId);
        Order order = new Order();
        order.setOrderId(orderId);
        if (stateMachine == null) {
            if (OrderEvent.PAY.name().equals(event)) {
                stateMachine = orderStateMachineBuilder.build(beanFactory);
                stateMachine.start();
                MemoryStateMachineMap.FORM_STATE_MACHINE_MAP.put(orderId, stateMachine);
            } else {
                log.info("该订单流程尚未开始，不能做[{}]转换", event);
                return "ERROR";
            }
            Message message = MessageBuilder.withPayload(OrderEvent.valueOf(event)).setHeader(Order.class.getName(), order).setHeader("TestOrderObject", "TestOrderObject").build();
            stateMachine.sendEvent(message);
        }
        return "SUCCESSS";

    }

    /**
     * 保存状态机
     *
     * @author heyingcheng
     * @date 2020/10/23
     */
    @PostMapping("/order/memory/persister")
    public String orderMemoryPersister(String orderId) throws Exception {

        StateMachine<OrderState, OrderEvent> stateMachine = orderStateMachineBuilder.build(beanFactory);
        // 创建流程
        stateMachine.start();
        //发送PAY事件
        Order order = new Order();
        order.setOrderId(orderId);
        Message<OrderEvent> message = MessageBuilder.withPayload(OrderEvent.PAY).setHeader(Order.class.getName(), order).build();
        stateMachine.sendEvent(message);

        // 持久化stateMachine
        orderMemoryStateMachinePersister.persist(stateMachine, order.getOrderId());
        return "SUCCESSS";

    }

    /**
     * 取出状态机
     *
     * @author heyingcheng
     * @date 2020/10/3
     */
    @PostMapping("/order/memory/persister/restore")
    public String orderMemoryPersisterRestore(String orderId) throws Exception {

        StateMachine<OrderState, OrderEvent> stateMachine = orderStateMachineBuilder.build(beanFactory);
        orderMemoryStateMachinePersister.restore(stateMachine, orderId);
        log.info("orderId:[{}], 恢复状态机后的状态为:[{}]", orderId, stateMachine.getState().getId());
        return "SUCCESSS";

    }

    /**
     * 保存状态机
     *
     * @author heyingcheng
     * @date 2020/10/23
     */
    @PostMapping("/order/db/persister")
    public String orderDbPersister(String orderId) throws Exception {

        StateMachine<OrderState, OrderEvent> stateMachine = orderStateMachineBuilder.build(beanFactory);
        // 创建流程
        stateMachine.start();
        //发送PAY事件
        Order order = new Order();
        order.setOrderId(orderId);
        Message<OrderEvent> message = MessageBuilder.withPayload(OrderEvent.PAY).setHeader(Order.class.getName(), order).build();
        stateMachine.sendEvent(message);
        // 持久化stateMachine
        orderMemoryStateMachinePersister.persist(stateMachine, order.getOrderId());
        return "SUCCESSS";

    }

    @PostMapping("/order/db/persister/restore")
    public void orderDbPersisterRestore(String orderId) throws Exception {

        StateMachine<OrderState, OrderEvent> stateMachine = orderStateMachineBuilder.build(beanFactory);
        //订单
        Order order = new Order();
        order.setOrderId(orderId);
        order.setOrderState(OrderState.WAITING_FOR_RECEIVE.code);
        //恢复
        orderDbStateMachinePersister.restore(stateMachine, order);
        //查看恢复后状态机的状态
        log.info("OrderId:[{}], 恢复状态机后的状态为:[{}]", orderId, stateMachine.getState().getId());

    }

}
